home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / tiff / tools / gif2tiff.c < prev    next >
C/C++ Source or Header  |  1992-01-28  |  9KB  |  391 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/gif2tiff.c,v 1.5 92/01/29 11:33:04 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  *    convert a GIF file into a TIFF file.
  7.  *    based on Paul Haeberli's fromgif program which in turn is
  8.  *    based on a GIF file reader by Marcel J.E. Mol March 23 1989 
  9.  *
  10.  *    if input is 320 by 200 pixel aspect is probably 1.2
  11.  *    if input is 640 350 pixel aspect is probably 1.37
  12.  *
  13.  */
  14. #include "tiffio.h"
  15. #include <math.h>
  16. #include <stdio.h>
  17.  
  18. #if defined(SYSV) || defined(THINK_C) || defined(applec) || defined(VMS)
  19. #define    bcopy(src,dst,len)    memcpy(dst, src, len)
  20. #endif
  21.  
  22. #define    GIFGAMMA    (1.5)        /* smaller makes output img brighter */
  23. #define    IMAX        ((1<<16)-1)    /* max intensity value */
  24. #define EXTRAFUDGE    128        /* some people write BAD .gif files */
  25.  
  26. short gamtab[256];
  27.  
  28. makegamtab(gam)
  29. float gam;
  30. {
  31.     int i;
  32.  
  33.     for(i=0; i<256; i++) 
  34.     gamtab[i] = IMAX*pow(i/255.0,gam)+0.5;
  35. }
  36.  
  37. short rbuf[8192];
  38. short gbuf[8192];
  39. short bbuf[8192];
  40.  
  41. #define COLSIZE 256
  42.  
  43. unsigned char *stackp;
  44. unsigned int prefix[4096];
  45. unsigned char suffix[4096];
  46. unsigned char stack[4096];
  47. int datasize,codesize,codemask;     /* Decoder working variables */
  48. int clear,eoi;                      /* Special code values */
  49. int avail, oldcode;
  50.  
  51. FILE *infile;
  52. int global;                        /* Is there a global color map? */
  53. int globalbits;                     /* Number of bits of global colors */
  54. unsigned char globalmap[COLSIZE][3];/* RGB values for global color map */
  55. char bgcolor;                       /* background color */
  56. unsigned char *raster;              /* Decoded image data */
  57. unsigned int width, height;
  58. unsigned short red[COLSIZE];
  59. unsigned short green[COLSIZE];
  60. unsigned short blue[COLSIZE];
  61. char *filename, *imagename;
  62.  
  63. main(argc,argv)
  64. int argc;
  65. char *argv[];
  66. {
  67.     extern int optind;
  68.     extern char *optarg;
  69.     int flag;
  70.  
  71.     makegamtab(GIFGAMMA);
  72.     if(argc<2) {
  73.     fprintf(stderr,"usage: gif2tif image.gif image.tif\n");
  74.     exit(1);
  75.     }
  76.     filename = argv[1];
  77.     imagename = argv[2];
  78.     if ((infile = fopen(filename,"r")) == NULL) {
  79.     perror(filename);
  80.     exit(1);
  81.     }
  82.     convert();
  83.     fclose(infile);
  84.     exit(0);
  85. }
  86.  
  87. convert()
  88. {
  89.     char ch;
  90.  
  91.     if (checksignature())
  92.         return;
  93.     readscreen();
  94.     while ((ch = getc(infile)) != ';' && ch != EOF) {
  95.         switch (ch) {
  96.             case '\0':  break;  /* this kludge for non-standard files */
  97.             case ',':   if (readgifimage())
  98.                            return;
  99.                         break;
  100.             case '!':   readextension();
  101.                         break;
  102.             default:    fprintf(stderr, "illegal GIF block type\n");
  103.                         return;
  104.                         break;
  105.         }
  106.     }
  107. }
  108.  
  109. checksignature()
  110. {
  111.     char buf[6];
  112.  
  113.     fread(buf,1,6,infile);
  114.     if (strncmp(buf,"GIF",3)) {
  115.         fprintf(stderr, "file is not a GIF file\n");
  116.         return 1;
  117.     }
  118.     if (strncmp(&buf[3],"87a",3)) {
  119.         fprintf(stderr, "unknown GIF version number\n");
  120.         return 1;
  121.     }
  122.     return 0;
  123. }
  124.  
  125. /*
  126.  *     readscreen - 
  127.  *        Get information which is global to all the images stored 
  128.  *    in the file
  129.  */
  130. readscreen()
  131. {
  132.     unsigned char buf[7];
  133.  
  134.     fread(buf,1,7,infile);
  135.     global = buf[4] & 0x80;
  136.     if (global) {
  137.         globalbits = (buf[4] & 0x07) + 1;
  138.         fread(globalmap,3,1<<globalbits,infile);
  139.     }
  140.     bgcolor = buf[5];
  141. }
  142.  
  143. readgifimage()
  144. {
  145.     unsigned char buf[9];
  146.     int local, interleaved;
  147.     char localmap[256][3];
  148.     int localbits;
  149.     register row;
  150.     register i;
  151.  
  152.     if (fread(buf, 1, 9, infile) == 0) {
  153.         perror(filename);
  154.         exit(1);
  155.     }
  156.     width = buf[4] + (buf[5] << 8);
  157.     height = buf[6] + (buf[7] << 8);
  158.     local = buf[8] & 0x80;
  159.     interleaved = buf[8] & 0x40;
  160.  
  161.     if (local == 0 && global == 0) {
  162.         fprintf(stderr, "no colormap present for image\n");
  163.         return 1;
  164.     }
  165.     if ((raster = (unsigned char*) malloc(width*height+EXTRAFUDGE)) == NULL) {
  166.         fprintf(stderr, "not enough memory for image\n");
  167.         return 1;
  168.     }
  169.     if (readraster(width, height))
  170.         return 1;
  171.     if (local) {
  172.         localbits = (buf[8] & 0x7) + 1;
  173.  
  174.         fprintf(stderr, "   local colors: %d\n", 1<<localbits);
  175.  
  176.         fread(localmap, 3, 1<<localbits, infile);
  177.         initcolors(localmap, 1<<localbits, bgcolor);
  178.     } else if (global) {
  179.         initcolors(globalmap, 1<<globalbits, bgcolor);
  180.     }
  181.     rasterize(interleaved, raster);
  182.     free(raster);
  183.     return 0;
  184. }
  185.  
  186. /*
  187.  *     readextension -
  188.  *        Read a GIF extension block (and do nothing with it).
  189.  *
  190.  */
  191. readextension()
  192. {
  193.     int count;
  194.     char buf[255];
  195.  
  196.     (void) getc(infile);
  197.     while (count = getc(infile))
  198.         fread(buf, 1, count, infile);
  199. }
  200.  
  201. /*
  202.  *     readraster -
  203.  *        Decode a raster image
  204.  *
  205.  */
  206. readraster(width, height)
  207. unsigned width,height;
  208. {
  209.     unsigned char *fill = raster;
  210.     unsigned char buf[255];
  211.     register bits=0;
  212.     register unsigned datum=0;
  213.     register unsigned char *ch;
  214.     register int count, code;
  215.  
  216.     datasize = getc(infile);
  217.     clear = 1 << datasize;
  218.     eoi = clear + 1;
  219.     avail = clear + 2;
  220.     oldcode = -1;
  221.     codesize = datasize + 1;
  222.     codemask = (1 << codesize) - 1;
  223.     for (code = 0; code < clear; code++) {
  224.     prefix[code] = 0;
  225.     suffix[code] = code;
  226.     }
  227.     stackp = stack;
  228.     for (count = getc(infile); count > 0; count = getc(infile)) {
  229.     fread(buf,1,count,infile);
  230.     for (ch=buf; count-- > 0; ch++) {
  231.         datum += *ch << bits;
  232.         bits += 8;
  233.         while (bits >= codesize) {
  234.         code = datum & codemask;
  235.         datum >>= codesize;
  236.         bits -= codesize;
  237.         if (code == eoi) {               /* This kludge put in */
  238. #ifdef DEBUG
  239.     fprintf(stderr, "found eoi code\n");
  240. #endif
  241.             goto exitloop;               /* because some GIF files*/
  242.         }                                /* aren't standard */
  243.         if (process(code, &fill)) {
  244.             goto exitloop;
  245.         }
  246.         }
  247.     }
  248.     if (fill >= raster + width*height) {
  249.         fprintf(stderr, "raster full before eoi code\n");
  250.         goto exitloop;
  251.     }
  252.     }
  253. exitloop:
  254.     if (fill != raster + width*height)  {
  255.     fprintf(stderr, "warning: wrong rastersize: %ld bytes\n",
  256.                               (long) (fill-raster));
  257.     fprintf(stderr, "         instead of %ld bytes\n",
  258.                               (long) width*height);
  259.     return 0; /* can still draw a picture ... */
  260.     }
  261.     return 0;
  262. }
  263.  
  264. /*
  265.  *     process - 
  266.  *        Process a compression code.  "clear" resets the code table.  
  267.  *    Otherwise make a new code table entry, and output the bytes 
  268.  *    associated with the code.
  269.  */
  270. process(code, fill)
  271. register code;
  272. unsigned char **fill;
  273. {
  274.     int incode;
  275.     static unsigned char firstchar;
  276.  
  277.     if (code == clear) {
  278.     codesize = datasize + 1;
  279.     codemask = (1 << codesize) - 1;
  280.     avail = clear + 2;
  281.     oldcode = -1;
  282.     return 0;
  283.     }
  284.  
  285.     if (oldcode == -1) {
  286.     *(*fill)++ = suffix[code];
  287.     firstchar = oldcode = code;
  288.     return 0;
  289.     }
  290.     if (code > avail) {
  291.     fprintf(stderr, "code % d to large for %d\n", code, avail);
  292.     return 1; 
  293.     }
  294.  
  295.     incode = code;
  296.     if (code == avail) {      /* the first code is always < avail */
  297.     *stackp++ = firstchar;
  298.     code = oldcode;
  299.     }
  300.     while (code > clear) {
  301.     *stackp++ = suffix[code];
  302.     code = prefix[code];
  303.     }
  304.  
  305.     *stackp++ = firstchar = suffix[code];
  306.     prefix[avail] = oldcode;
  307.     suffix[avail] = firstchar;
  308.     avail++;
  309.  
  310.     if (((avail & codemask) == 0) && (avail < 4096)) {
  311.     codesize++;
  312.     codemask += avail;
  313.     }
  314.     oldcode = incode;
  315.     do {
  316.     *(*fill)++ = *--stackp;
  317.     } while (stackp > stack);
  318.     return 0;
  319. }
  320.  
  321. /*
  322.  *     initcolors -
  323.  *        Convert a color map (local or global) to arrays with R, G and B
  324.  *     values. 
  325.  *
  326.  */
  327. initcolors(colormap, ncolors, bgcolor)
  328. unsigned char colormap[COLSIZE][3];
  329. int ncolors;
  330. int bgcolor;
  331. {
  332.     register i, k;
  333.  
  334.     for (i = 0; i < ncolors; i++) {
  335.         red[i]   = gamtab[colormap[i][0]];
  336.         green[i] = gamtab[colormap[i][1]];
  337.         blue[i]  = gamtab[colormap[i][2]];
  338.     }
  339. }
  340.  
  341. rasterize(interleaved, raster)
  342. int interleaved;
  343. register unsigned char *raster;
  344. {
  345.     register row, col;
  346.     register unsigned char *rr;
  347.     unsigned char *newras;
  348.     TIFF *tif;
  349.     
  350. #define DRAWSEGMENT(offset, step)                       \
  351.         for (row = offset; row < height; row += step) { \
  352.             rr = newras + row*width;                   \
  353.             bcopy(raster, rr, width);                   \
  354.             raster += width;                            \
  355.         }
  356.  
  357.     if ((newras = (unsigned char*) malloc(width*height+EXTRAFUDGE)) == NULL) {
  358.         fprintf(stderr, "not enough memory for image\n");
  359.         return 1;
  360.     }
  361.     if (interleaved) {
  362.         DRAWSEGMENT(0, 8);
  363.         DRAWSEGMENT(4, 8);
  364.         DRAWSEGMENT(2, 4);
  365.         DRAWSEGMENT(1, 2);
  366.     }
  367.     else 
  368.         DRAWSEGMENT(0, 1);
  369.  
  370.     tif = TIFFOpen(imagename, "w");
  371.     if (!tif) {
  372.     TIFFError(imagename,"Can not open output image");
  373.     exit(-1);
  374.     }
  375.     TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
  376.     TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
  377.     TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
  378.     TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
  379.     TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  380.     TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
  381.     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
  382.     TIFFSetField(tif, TIFFTAG_COLORMAP, red, green, blue);
  383.     TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  384.     for(row=0; row<height; row++)
  385.     if (TIFFWriteScanline(tif, newras+row*width, row, 0) < 0)
  386.         break;
  387.     TIFFClose(tif);
  388.  
  389.     free(newras);
  390.